package br.com.puertorico.model.querybuilder.sorting;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author Daniel Camargo
 *
 */
public abstract class SortStrategy implements Serializable {

	private static final long serialVersionUID = 8109972757765227190L;

	/**
	 * Um map contendo todos os campos de ordenacao que serao considerados na
	 * busca
	 */
	private Map<String, SortItem> sortItemMap;

	/**
	 * Tem o objetivo de conseguir uma lista em ordem dos campos que serao
	 * utilizados para ordenar a consulta
	 *
	 * @return
	 */
	public final List<SortItem> getSortItemList() {
		if (sortItemMap == null) {
			sortItemMap = new HashMap<String, SortItem>();
		}
		List<SortItem> items = new ArrayList<SortItem>();
		for (String key : sortItemMap.keySet()) {
			items.add(sortItemMap.get(key));
		}
		Collections.sort(items);
		return items;
	}

	/**
	 * Para recuperar o map verificando a necessidade de instancia-lo
	 *
	 * @return
	 */
	public Map<String, SortItem> getSortItemMap() {
		if (sortItemMap == null) {
			sortItemMap = new HashMap<String, SortItem>();
		}
		return sortItemMap;
	}

	/**
	 * Percorre a lista de campos atual em busca do campo cujo nome seja igual
	 * ao nome passado por parametro
	 *
	 * @param columnName
	 * @return
	 */
	public SortItem getItemByColumnName(String columnName) {
		for (SortItem item : getSortItemList()) {
			if (item.getColumnName().equals(columnName)) {
				return item;
			}
		}
		return null;
	}

	/**
	 * Metodo responsavel por montar a clausula ORDER BY
	 *
	 * @return a clausula ORDER BY definida pelos elementos da lista
	 */
	public String getOrderByClause() {
		StringBuilder orderByClause = new StringBuilder();
		boolean isOrderByPlaced = false;
		for (SortItem item : getSortItemList()) {
			if (!isOrderByPlaced) {
				isOrderByPlaced = true;
				orderByClause.append("ORDER BY");
			} else {
				orderByClause.append(",");
			}
			orderByClause.append(" ").append(item.getColumnName()).append(" ");
			orderByClause.append(item.getAsc() ? "ASC" : "DESC");
		}
		return orderByClause.toString();
	}

	/**
	 * A forma como os itens sao adicionados vai depender de cada estrategia
	 * utilizada. A ideia eh permitir que a ordem dos itens seja alterada de
	 * acordo com a exigencia da aplicacao
	 *
	 * @param columnName
	 */
	public abstract void addSortItem(String columnName);

	public void setSortItemMap(Map<String, SortItem> sortItemMap) {
		this.sortItemMap = sortItemMap;
	}

}
